package process.service.impl;

import gate.util.GateException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import process.model.MenuItem;
import process.model.MenuNode;
import process.model.event.MenuEvent;
import process.service.MenuParserService;

import com.google.common.eventbus.EventBus;

import core.constant.SystemConstant;

@Service
public class MenuParserServiceImpl implements MenuParserService {

	@Autowired
	private EventBus eventBus;

	@PostConstruct
	public void initialize() {
		eventBus.register(this);
	}

	public List<MenuItem> parse(long storeId, String siteUrl, String menuQ,
			String paginatorQ) throws IOException {
		List<MenuItem> menuItems = new ArrayList<MenuItem>();
		Connection connection = Jsoup.connect(siteUrl);
		// Connection connection = Jsoup.connect("http://www.nguyenkim.com/");
		// Connection connection =
		// Jsoup.connect("http://www.dienmaythienhoa.vn/");
		connection.timeout(30 * 1000);

		Document doc = connection.get();
		Elements elements = doc.select(menuQ);
		// Elements elements = doc.select(".wrap-dropdown-multicolumns");
		// Elements elements = doc.select(".ddsmoothmenu");
		int depth = 0;
		List<MenuNode> list = new ArrayList<MenuNode>();
		for (Element element : elements) {

			recursiveByDepth(list, element, new Integer(depth));

		}

		List<MenuNode> results = new ArrayList<MenuNode>();

		for (int i = 0; i < list.size(); i++) {
			MenuNode menuNode = list.get(i);

			if (i < list.size() - 1) {
				if (menuNode.getDepth() < list.get(i + 1).getDepth()) {
					list.get(i + 1).setParent(menuNode);
					continue;
				} else if (menuNode.getDepth() == list.get(i + 1).getDepth()) {
					list.get(i + 1).setParent(menuNode.getParent());
					results.add(menuNode);
				} else {
					list.get(i + 1).setParent(menuNode.getParent().getParent());
					results.add(menuNode);
				}

			} else {
				results.add(menuNode);
			}

		}

		for (MenuNode node : results) {
			// for (int i = 137; i < results.size(); i++) {
			// MenuNode node = results.get(i);

			System.out.println(node.getUrl());
			connection = Jsoup.connect(node.getUrl());
			connection.timeout(SystemConstant.CONNECT_TIMEOUT);
			doc = connection.get();
			elements = doc.select(paginatorQ);
			// elements = doc.select(".pagination");
			if (!elements.isEmpty()) {
				for (Element element : elements) {
					Elements anchors = element.select("a[href]");
					Set<String> ancs = new HashSet<String>();
					for (Element anchor : anchors) {
						ancs.add(anchor.absUrl("href"));
					}
					ancs.add(node.getUrl());
					MenuItem menuItem = new MenuItem(node,
							new ArrayList<String>(ancs));

					menuItems.add(menuItem);
					eventBus.post(new MenuEvent(menuItem, storeId));
				}
			} else {
				List<String> ancs = new ArrayList<String>();
				ancs.add(node.getUrl());
				MenuItem menuItem = new MenuItem(node, ancs);
				menuItems.add(menuItem);
				eventBus.post(new MenuEvent(menuItem, storeId));
			}
		}

		return menuItems;
	}

	private static void recursiveByDepth(List<MenuNode> list, Element element,
			Integer depth) {
		if (element.tagName().equals("a")) {
			list.add(new MenuNode(element.absUrl("href"), depth, element
					.ownText()));
		}

		Elements elements = element.children();
		for (Element e : elements) {
			recursiveByDepth(list, e, new Integer(depth + 1));
		}

	}

	public static void main(String[] args) throws IOException, GateException {
		MenuParserService menuParser = new MenuParserServiceImpl();
		menuParser.parse(1, "http://www.nguyenkim.com/",
				".wrap-dropdown-multicolumns", ".pagination");
	}

}
